home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 1.iso / DEMON / RISCOS2 / TCP_131S.ARC / c / TCPUSER < prev    next >
Text File  |  1992-10-23  |  10KB  |  323 lines

  1. /* User calls to TCP */
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #include <stdarg.h>
  6. #include "global.h"
  7. #include "timer.h"
  8. #include "mbuf.h"
  9. #include "netuser.h"
  10. #include "nntp.h"
  11. #include "internet.h"
  12. #include "tcp.h"
  13.  
  14. int16 tcp_window = DEF_WND;
  15.  
  16. struct tcb *open_tcp(struct socket *lsocket, struct socket *fsocket,
  17.                      int mode, int16 window, void (*r_upcall)(),
  18.                      void (*t_upcall)(), void (*s_upcall)(),
  19.                      char tos, char *user)
  20. {
  21.         struct connection conn;
  22.         register struct tcb *tcb;
  23.  
  24.         if(lsocket == NULLSOCK){
  25.                 net_error = INVALID;
  26.                 return NULLTCB;
  27.         }
  28.         conn.local.address = lsocket->address;
  29.         conn.local.port = lsocket->port;
  30.         if(fsocket != NULLSOCK){
  31.                 conn.remote.address = fsocket->address;
  32.                 conn.remote.port = fsocket->port;
  33.         } else {
  34.                 conn.remote.address = 0;
  35.                 conn.remote.port = 0;
  36.         }
  37.         if((tcb = lookup_tcb(&conn)) == NULLTCB){
  38.                 if((tcb = create_tcb(&conn)) == NULLTCB){
  39.                         net_error = NO_SPACE;
  40.                         return NULLTCB;
  41.                 }
  42.         } else if(tcb->state != LISTEN){
  43.                 net_error = CON_EXISTS;
  44.                 return NULLTCB;
  45.         }
  46.         tcb->user = user;
  47.         if(window != 0)
  48.                 tcb->window = tcb->rcv.wnd = window;
  49.         else
  50.                 tcb->window = tcb->rcv.wnd = tcp_window;
  51.         tcb->r_upcall = r_upcall;
  52.         tcb->t_upcall = t_upcall;
  53.         tcb->s_upcall = s_upcall;
  54.         tcb->tos = tos;
  55.         switch(mode){
  56.         case TCP_SERVER:
  57.                 tcb->flags |= CLONE;
  58.         case TCP_PASSIVE:       /* Note fall-thru */
  59.                 setstate(tcb,LISTEN);
  60.                 break;
  61.         case TCP_ACTIVE:
  62.                 /* Send SYN, go into SYN_SENT state */
  63.                 tcb->flags |= ACTIVE;
  64.                 send_syn(tcb);
  65.                 setstate(tcb,SYN_SENT);
  66.                 tcp_output(tcb);
  67.                 tcp_stat.conout++;
  68.                 break;
  69.         }
  70.         return tcb;
  71. }
  72. /* User send routine */
  73. int send_tcp(register struct tcb *tcb, struct mbuf *bp)
  74. {
  75.         int16 cnt;
  76.  
  77.         if(tcb == NULLTCB || bp == NULLBUF){
  78.                 free_p(bp);
  79.                 net_error = INVALID;
  80.                 return -1;
  81.         }
  82.         cnt = len_mbuf(bp);
  83. #ifdef  TIGHT
  84.         /* If this would overfill our send queue, reject it entirely */
  85.         if(tcb->sndcnt + cnt > tcb->window){
  86.                 free_p(bp);
  87.                 net_error = WOULDBLK;
  88.                 return -1;
  89.         }
  90. #endif
  91.         switch(tcb->state){
  92.         case CLOSED:
  93.                 free_p(bp);
  94.                 net_error = NO_CONN;
  95.                 return -1;
  96.         case LISTEN:    /* Change state from passive to active */
  97.                 tcb->flags |= ACTIVE;
  98.                 send_syn(tcb);
  99.                 setstate(tcb,SYN_SENT); /* Note fall-thru */
  100.         case SYN_SENT:
  101.         case SYN_RECEIVED:
  102.         case ESTABLISHED:
  103.         case CLOSE_WAIT:
  104.                 append(&tcb->sndq,bp);
  105.                 tcb->sndcnt += cnt;
  106.                 tcp_output(tcb);
  107.                 break;
  108.         case FINWAIT1:
  109.         case FINWAIT2:
  110.         case CLOSING:
  111.         case LAST_ACK:
  112.         case TIME_WAIT:
  113.                 free_p(bp);
  114.                 net_error = CON_CLOS;
  115.                 return -1;
  116.         }
  117.         return cnt;
  118. }
  119. /* User receive routine */
  120. int recv_tcp(register struct tcb *tcb, struct mbuf **bp, int16 cnt)
  121. {
  122.         if(tcb == NULLTCB || bp == (struct mbuf **)NULL){
  123.                 net_error = INVALID;
  124.                 return -1;
  125.         }
  126.         /* cnt == 0 means "I want it all" */
  127.         if(cnt == 0)
  128.                 cnt = tcb->rcvcnt;
  129.         /* If there's something on the queue, just return it regardless
  130.          * of the state we're in.
  131.          */
  132.         if(tcb->rcvcnt != 0){
  133.                 /* See if the user can take all of it */
  134.                 if(tcb->rcvcnt <= cnt){
  135.                         cnt = tcb->rcvcnt;
  136.                         *bp = tcb->rcvq;
  137.                         tcb->rcvq = NULLBUF;
  138.                 } else {
  139.                         if((*bp = alloc_mbuf(cnt)) == NULLBUF){
  140.                                 net_error = NO_SPACE;
  141.                                 return -1;
  142.                         }
  143.                         pullup(&tcb->rcvq,(*bp)->data,cnt);
  144.                         (*bp)->cnt = cnt;
  145.                 }
  146.                 tcb->rcvcnt -= cnt;
  147.                 tcb->rcv.wnd += cnt;
  148.                 /* Do a window update if it was closed */
  149.                 if(cnt == tcb->rcv.wnd){
  150.                         tcb->flags |= FORCE;
  151.                         tcp_output(tcb);
  152.                 }
  153.                 return cnt;
  154.         } else {
  155.                 /* If there's nothing on the queue, our action depends on what state
  156.                  * we're in (i.e., whether or not we're expecting any more data).
  157.                  * If no more data is expected, then simply return 0; this is
  158.                  * interpreted as "end of file".
  159.                  */
  160.                 switch(tcb->state){
  161.                 case LISTEN:
  162.                 case SYN_SENT:
  163.                 case SYN_RECEIVED:
  164.                 case ESTABLISHED:
  165.                 case FINWAIT1:
  166.                 case FINWAIT2:
  167.                         *bp = NULLBUF;
  168.                         net_error = WOULDBLK;
  169.                         return -1;
  170.                 case CLOSED:
  171.                 case CLOSE_WAIT:
  172.                 case CLOSING:
  173.                 case LAST_ACK:
  174.                 case TIME_WAIT:
  175.                         *bp = NULLBUF;
  176.                         return 0;
  177.                 }
  178.         }
  179.         return 0;       /* Not reached, but lint doesn't know that */
  180. }
  181. /* This really means "I have no more data to send". It only closes the
  182.  * connection in one direction, and we can continue to receive data
  183.  * indefinitely.
  184.  */
  185. int close_tcp(register struct tcb *tcb)
  186. {
  187.         if(tcb == NULLTCB){
  188.                 net_error = INVALID;
  189.                 return -1;
  190.         }
  191.         switch(tcb->state){
  192.         case CLOSED:
  193.                 return 0;       /* Unlikely */
  194.         case LISTEN:
  195.         case SYN_SENT:
  196.                 close_self(tcb,NORMAL);
  197.                 return 0;
  198.         case SYN_RECEIVED:
  199.         case ESTABLISHED:
  200.                 tcb->sndcnt++;
  201.                 tcb->snd.nxt++;
  202.                 setstate(tcb,FINWAIT1);
  203.                 tcp_output(tcb);
  204.                 return 0;
  205.         case CLOSE_WAIT:
  206.                 tcb->sndcnt++;
  207.                 tcb->snd.nxt++;
  208.                 setstate(tcb,LAST_ACK);
  209.                 tcp_output(tcb);
  210.                 return 0;
  211.         case FINWAIT1:
  212.         case FINWAIT2:
  213.         case CLOSING:
  214.         case LAST_ACK:
  215.         case TIME_WAIT:
  216.                 net_error = CON_CLOS;
  217.                 return -1;
  218.         }
  219.         return -1;      /* "Can't happen" */
  220. }
  221. /* Delete TCB, free resources. The user is not notified, even if the TCB is
  222.  * not in the CLOSED state. This function should normally be called by the
  223.  * user only in response to a state change upcall to CLOSED state.
  224.  */
  225. int del_tcp(register struct tcb *tcb)
  226. {
  227.         struct reseq *rp,*rp1;
  228.  
  229.         if(tcb == NULLTCB){
  230.                 net_error = INVALID;
  231.                 return -1;
  232.         }
  233.         unlink_tcb(tcb);
  234.         stop_timer(&tcb->timer);
  235.         stop_timer(&tcb->rtt_timer);
  236.         for(rp = tcb->reseq;rp != NULLRESEQ;rp = rp1){
  237.                 rp1 = rp->next;
  238.                 free_p(rp->bp);
  239.                 free((char *)rp);
  240.         }
  241.         tcb->reseq = NULLRESEQ;
  242.         free_p(tcb->rcvq);
  243.         free_p(tcb->sndq);
  244.         free((char *)tcb);
  245.         return 0;
  246. }
  247. /* Do printf on a tcp connection */
  248. int tprintf(struct tcb *tcb, char *message, ...)
  249. {
  250.         va_list argptr;
  251.         struct mbuf *bp;
  252.         int len;
  253.  
  254.         if(tcb == NULLTCB)
  255.                 return 0;
  256.  
  257.         if ((bp = alloc_mbuf(160)) == NULLBUF)
  258.                 return 0;
  259.  
  260.         va_start(argptr,message);
  261.         len = vsprintf(bp->data,message,argptr);
  262.         va_end(argptr);
  263.         bp->cnt = strlen(bp->data);
  264.         send_tcp(tcb,bp);
  265.         return len;
  266. }
  267. /* Return 1 if arg is a valid TCB, 0 otherwise */
  268. int tcpval(struct tcb *tcb)
  269. {
  270.         register int i;
  271.         register struct tcb *tcb1;
  272.  
  273.         if(tcb == NULLTCB)
  274.                 return 0;       /* Null pointer can't be valid */
  275.         for(i=0;i<NTCB;i++){
  276.                 for(tcb1=tcbs[i];tcb1 != NULLTCB;tcb1 = tcb1->next){
  277.                         if(tcb1 == tcb)
  278.                                 return 1;
  279.                 }
  280.         }
  281.         return 0;
  282. }
  283. int kick_tcp(register struct tcb *tcb)
  284. {
  285.         if(!tcpval(tcb))
  286.                 return -1;
  287.         tcp_timeout((char *)tcb);
  288.         return 0;
  289. }
  290. void reset_tcp(register struct tcb *tcb)
  291. {
  292.         close_self(tcb,RESET);
  293. }
  294. /* Return character string corresponding to a TCP well-known port, or
  295.  * the decimal number if unknown.
  296.  */
  297. char *tcp_port(int16 n)
  298. {
  299.         static char buf[32];
  300.  
  301.         switch(n){
  302.         case ECHO_PORT:
  303.                 return "echo";
  304.         case DISCARD_PORT:
  305.                 return "discard";
  306.         case FTPD_PORT:
  307.                 return "ftp_data";
  308.         case FTP_PORT:
  309.                 return "ftp";   
  310.         case TELNET_PORT:
  311.                 return "telnet";
  312.         case SMTP_PORT:
  313.                 return "smtp";
  314.         case FINGER_PORT:
  315.                 return "finger";
  316.         case NNTP_PORT:
  317.                 return "nntp";
  318.         default:
  319.                 sprintf(buf,"%u",n);
  320.                 return buf;
  321.         }
  322. }
  323.